﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Windows.Interop;
using System.ComponentModel;
using System.Windows.Media.Imaging;
using System.Windows;
using System.Collections.ObjectModel;
using System.Diagnostics;
using ReaderWriter.Providers;

namespace ReaderWriter.IO
{
    public abstract class ViewModelNode:INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public void Raise(string name="")
        {
            if (string.IsNullOrEmpty(name))
            {
                StackTrace stackTrace = new StackTrace();
                var cool = stackTrace.GetFrame(1).GetMethod();
                name = cool.Name;
            }
            if (PropertyChanged != null)
            {
                PropertyChanged( this, new PropertyChangedEventArgs(name));
            }
        }
        public void SetValue(ref object destination, object source, string name="")
        {
            if (destination.GetType() == source.GetType())
            {
                destination = source;
                Raise(name);
            }
        }
    }
    public enum StorageType
    {
        Drive, Folder, File
    }
    public class StorageNode:ViewModelNode
    {
       
        public StorageNode(IReaderWriter controller)
        {
            iO = controller;
            _created = DateTime.UtcNow;
            _updated = DateTime.UtcNow;
            _children = new BindingList<StorageNode>();
            _children.AddingNew += new AddingNewEventHandler((sender, e) =>
            {
                Raise("Name");
                Raise("Children");
            });
        }
        protected StorageNode()
        {
            _created = DateTime.UtcNow;
            _updated = DateTime.UtcNow;
            _children = new BindingList<StorageNode>();
            _children.AddingNew += new AddingNewEventHandler((sender, e) =>
            {
                Raise("Name");
                Raise("Children");
            });
        }
        IReaderWriter iO;

        public IReaderWriter IO
        {
            get { return iO; }
            set { iO = value; }
        }
        long _internalID;

        public long InternalID
        {
            get { return _internalID; }
            set { _internalID = value; Raise(); }
        }
        bool _hidden;

        public bool Hidden
        {
            get { return _hidden; }
            set { _hidden = value; Raise(); }
        }
        string _name;

        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
        string _uri;

        public string Uri
        {
            get { return _uri; }
            set { _uri = value; }
        }
        DateTime _created;

        public DateTime Created
        {
            get { return _created; }
            set { _created = value; }
        }
        DateTime _updated;

        public DateTime Updated
        {
            get { return _updated; }
            set { _updated = value; }
        }
        string _user;

        public string User
        {
            get { return _user; }
            set { _user = value; }
        }
        StorageType _storageType;

        public StorageType StorageType
        {
            get { return _storageType; }
            set { _storageType = value; }
        }

        string _extn;

        public string Extn
        {
            get {
                try
                {
                    _extn = Name.Substring(Name.LastIndexOf('.'));
                }
                catch { 
                }
                return _extn; 
            }
            set { _extn = value; }
        }

        ImageSource _displayIcon = null;

        public ImageSource DisplayIcon
        {
            get
            {
                if (_displayIcon == null)
                {
                    try
                    {
                        if (StorageType == StorageType.Folder)
                        {
                            _displayIcon = IconExtractor.GetFolderIcon(FullName).ToImageSource();
                            // Lets put a Hook here
                            if (_displayIcon == null)
                            {
                                _displayIcon = IconExtractor.GetIconFromFileExtn(string.Empty).ToImageSource();
                            }
                        }
                        else
                        {
                            _displayIcon = IconExtractor.GetFileIcon(FullName).ToImageSource();
                            // Lets put a Hook here
                            if (_displayIcon == null)
                            {
                                _displayIcon = IconExtractor.GetIconFromFileExtn(Name).ToImageSource();
                            }
                        }
                    }
                    catch (Exception e)
                    {

                    }
                }

                return _displayIcon;
            }

            set { _displayIcon = value; }
        }

        bool _showToolTip;

        public bool ShowToolTip
        {
            get { return _showToolTip; }
            set { _showToolTip = value; }
        }
        int _indentation;

        public int Indentation
        {
            get { return _indentation; }
            set { _indentation = value; }
        }
        public virtual string FullName
        {
            get { return _uri; }
            set { _uri = value; }
        }
        BindingList<StorageNode> _children;

        public BindingList<StorageNode> Children
        {
            get { return _children; }
            set { _children = value; Raise("Children"); }
        }
        string _parentUri;

        public string ParentUri
        {
            get { return _parentUri; }
            set { _parentUri = value; }
        }
        FolderNode _parent;

        public FolderNode Parent
        {
            get { return _parent; }
            set { _parent = value; Raise(); }
        }
        string _mimeType;

        public string MimeType
        {
            get { return _mimeType; }
            set { _mimeType = value; }
        }
        byte[] _data;

        public byte[] Data
        {
            get { return _data; }
            set { _data = value; }
        }
        double _size;

        public double Size
        {
            get { return _size; }
            set { _size = value; Raise("Size"); Raise("Length"); }
        }

        public string Length
        {
            get
            {
                string size = "0 KB";
                if (Size < 1024)
                {
                    size = string.Format("{0:0.##} {1}", Size, "Bytes");
                }
                else if (Size  < 1024 * 1024)
                {
                    size = string.Format("{0:0.##} {1}", Size / 1024, "KB");
                }
                else if (Size < 1024 * 1024 * 1024)
                {
                    size = string.Format("{0:0.##} {1}", Size / (1024 * 1024), "MB");
                }
                else 
                {
                    size = string.Format("{0:0.##} {1}", Size / (1024 * 1024 * 1024), "GB");
                }
                return size;
            }
            set
            {
                Raise("Length");
            }
        }

        double _progress;

        public double Progress
        {
            get { return _progress; }
            set { _progress = value; Raise("Progress"); }
        }
        bool _started;

        public bool Started
        {
            get { return _started; }
            set { _started = value; Raise("Started"); Raise("ShowProgress"); Raise("ShowFullName"); }
        }
        bool _downloaded;

        public bool Downloaded
        {
            get { return _downloaded; }
            set { _downloaded = value; Raise("Downloaded"); Raise("ShowProgress"); Raise("ShowFullName"); }
        }

        bool isDragging;

        public bool IsDragging
        {
            get { return isDragging; }
            set { isDragging = value; Raise("IsDragging"); }
        }

        bool isSelected;

        public bool IsSelected
        {
            get { return isSelected; }
            set { isSelected = value; Raise("IsSelected"); }
        }

        bool isExpanded;

        public bool IsExpanded
        {
            get { return isExpanded; }
            set { isExpanded = value; Raise("IsExpanded"); }
        }
        public Visibility ShowProgress
        {
            get
            {
                if (_started) { return Visibility.Visible; }
                else return Visibility.Collapsed;
            }
            set { _started = true; }
        }
        public Visibility ShowFullName
        {
            get
            {
                if (!_started) { return Visibility.Visible; }
                else return Visibility.Collapsed;
            }
            set { _started = false; }
        }
       
        public void Add(StorageNode node)
        {
            _children.Add(node);
            Raise("Children");
        }
    }
    public class FileNode : StorageNode
    {
        public FileNode()
            : base(null)
        {
        }
        public FileNode(IReaderWriter io) : base(io)
        {
        }
        object _downloader;

        public object Downloader
        {
            get { return _downloader; }
            set { _downloader = value; }
        }
    }
    public class FolderNode : StorageNode
    {
        public FolderNode()
            : base(null)
        {
        }
        public FolderNode(IReaderWriter io) : base(io)
        {
            StorageType = ReaderWriter.IO.StorageType.Folder;
        }
        FolderNode _parent;
      
        public FolderNode Parent
        {
            get { return _parent; }
            set { _parent = value; Raise("Parent"); }
        }
        bool hasChildren;

        public bool HasChildren
        {
            get { return Children.Any(); }

        }

        bool isSelected = false;

        public bool IsSelected
        {
            get { return isSelected; }
            set { isSelected = value; 
                Raise("IsSelected"); }
        }
        bool isExpanded = true;

        public bool IsExpanded
        {
            get { return isExpanded; }
            set { 
            if (value != isExpanded)
            {
                isExpanded = value;
                Raise("IsExpanded");
            }

            // Expand all the way up to the root.
            if (isExpanded && _parent != null)
                _parent.IsExpanded = true;
            
            }
        }

    }

 
}
